package com.junjie.blibli.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.junjie.blibli.Constant.UserConstant;
import com.junjie.blibli.Entity.RefreshTokenDetail;
import com.junjie.blibli.Entity.User;
import com.junjie.blibli.Entity.UserInfo;
import com.junjie.blibli.Exception.http.ConditionException;
import com.junjie.blibli.dao.UserDao;
import com.junjie.blibli.result.PageResult;
import com.junjie.blibli.service.UserAuthService;
import com.junjie.blibli.service.UserService;
import com.junjie.blibli.util.MD5Util;
import com.junjie.blibli.util.RSAUtil;
import com.junjie.blibli.util.TokenUtil;
import com.mysql.cj.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class UserServiceImpl implements UserService  {
    @Autowired
    private UserDao userDao;

    @Autowired
    private UserAuthService userAuthService;

    @Override
    public void addUser(User user) {
        String phone = user.getPhone();
        if(StringUtils.isNullOrEmpty(phone)){
            throw new ConditionException("手机号不能为空");
        }
        User dbUser = this.getUserByPhone(phone);
        if(dbUser!=null){
            throw new ConditionException("该手机号已注册");
        }
        Date now = new Date();
        String salt = String.valueOf(now.getTime());
        String password = user.getPassword();
        String rawPassword;
        try {
            rawPassword = RSAUtil.decrypt(password);
        } catch (Exception e) {
            throw new ConditionException("密码解密失败");
        }
        String md5Password = MD5Util.sign(rawPassword,salt,"UTF-8");
        user.setSalt(salt);
        user.setPassword(md5Password);
        user.setCreateTime(now);
        userDao.addUser(user);
        //添加用户信息
        UserInfo userInfo = new UserInfo();
        userInfo.setUserId(user.getId());
        userInfo.setNick(UserConstant.DEFAULT_NICK);
        userInfo.setGender(UserConstant.GENDER_MALE);
        userInfo.setBirth(UserConstant.DEFAULT_BIRTH);
        userInfo.setCreateTime(now);
        userDao.addUserInfo(userInfo);

        //给用户添加默认角色
        userAuthService.addUserDefaultRole(user.getId());
    }

    @Override
    public String login(User user) throws Exception{
        String phone = user.getPhone();
        if(StringUtils.isNullOrEmpty(phone)){
            throw new ConditionException("手机号不能为空！");
        }
        User dbUser = this.getUserByPhone(phone);
        if(dbUser==null){
            throw new ConditionException("当前用户不存在");
        }
        String password = user.getPassword();
        try {
            password = RSAUtil.decrypt(password);
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("密码解密失败");
        }
        String salt = dbUser.getSalt();
        String md5Password = MD5Util.sign(password,salt,"UTF-8");
        if(!md5Password.equals(dbUser.getPassword())){
            throw new ConditionException("密码错误");
        }
        TokenUtil tokenUtil = new TokenUtil();
        return tokenUtil.generateToken(dbUser.getId());
    }

    @Override
    public User getUserInfo(Long userId) {
        User user = userDao.getUserById(userId);
        UserInfo userInfo = userDao.getUserInfoById(userId);
        user.setUserInfo(userInfo);
        return user;
    }

    @Override
    public void updateUserInfos(UserInfo userInfo) {
        userInfo.setUpdateTime(new Date());
        userDao.updateUserInfos(userInfo);
    }

    @Override
    public User getUserById(Long followingId) {
        return userDao.getUserById(followingId);
    }

    @Override
    public List<UserInfo> getUserInfoByIds(Set<Long> userIdList) {

        return userDao.getUserInfoByIds(userIdList);
    }

    @Override
    public PageResult<UserInfo> pageListUserInfos(JSONObject params) {
        Integer no = params.getInteger("no");
        Integer size = params.getInteger("size");
        //计算数据库的起点与终点
        params.put("start",(no-1)*size);
        params.put("limit",size);
        //先查询满足条件的总个数
        Integer total = userDao.pageCountUserInfos(params);
        List<UserInfo> list = new ArrayList<>();
        //如果数量>0就可以查询具体信息并返回
        if(total>0){
            list = userDao.pageListUserInfos(params);
        }
        return new PageResult<>(total,list);
    }

    @Override
    public Map<String, Object> loginForDts(User user) throws Exception{
        String phone = user.getPhone();
        if(StringUtils.isNullOrEmpty(phone)){
            throw new ConditionException("手机号不能为空！");
        }
        User dbUser = this.getUserByPhone(phone);
        if(dbUser==null){
            throw new ConditionException("当前用户不存在");
        }
        String password = user.getPassword();
        try {
            password = RSAUtil.decrypt(password);
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("密码解密失败");
        }
        String salt = dbUser.getSalt();
        String md5Password = MD5Util.sign(password,salt,"UTF-8");
        if(!md5Password.equals(dbUser.getPassword())){
            throw new ConditionException("密码错误");
        }
        TokenUtil tokenUtil = new TokenUtil();
        Long dbUserId = dbUser.getId();
        String accessToken = tokenUtil.generateToken(dbUserId);
        String refreshToken = TokenUtil.generateRefreshToken(dbUserId);
        //把refreshToken放到数据库里去 TODO 改成RedisLogin
        //方式是先删除再新增
        userDao.deleteRefreshToken(refreshToken,dbUserId);
        userDao.addRefreshToken(refreshToken,dbUserId,new Date());
        HashMap<String, Object> result = new HashMap<>();
        result.put("accessToken",accessToken);
        result.put("refreshToken",refreshToken);
        return result;
    }

    @Override
    public void logout(String refreshToken, Long userId) {
        //做一个删除操作就行了
        //TODO 改成redisLogout
        userDao.deleteRefreshToken(refreshToken,userId);
    }

    @Override
    public String refreshAccessToken(String refreshToken) throws Exception {
        RefreshTokenDetail refreshTokenDetail = userDao.getRefreshTokenDetail(refreshToken);
        if(refreshTokenDetail==null){
            throw new ConditionException("555","token过期!");
        }
        Long userId = refreshTokenDetail.getUserId();
        return TokenUtil.generateToken(userId);
    }

    public User getUserByPhone(String phone){
        return userDao.getUserByPhone(phone);
    }

    public List<UserInfo> batchGetUserInfoByUserIds(Set<Long> userIdList) {
        return userDao.batchGetUserInfoByUserIds(userIdList);
    }
}
